/*=============================================================================
#    The element-comm is a tentative program used to test our ideas.           
#                       Copyright (C)  bgao                                    
#
#     This program is free software; you can redistribute it and/or            
#      modify it under the terms of the GNU General Public License             
#     as published by the Free Software Foundation; either version 2           
#         of the License, or (at your option) any later version.               
#
#     This program is distributed in the hope that it will be useful,          
#    but WITHOUT ANY WARRANTY; without even the implied warranty of           
#     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            
#             GNU General Public License for more details.                    
#
#    You should have received a copy of the GNU General Public License        
#     along with this program; if not, write to the Free Software             
#      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,             
#                       MA  02110-1301, USA.                                  
#==============================================================================
# $Id$ 
#
# $Author$ 
#
# $Revision$ 
#
# $Date$ 
#
# Description: 
#
=============================================================================*/
#ifndef __RTOS_WSN_H__
#define __RTOS_WSN_H__


#include "wsn-cpu.h"
#include "wsn-cfg.h"

/*
*********************************************************************************************************
*                                          SenHopen VERSION NUMBER
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                             ERROR CODES
*********************************************************************************************************
*/
#define 	ERR_NONE 				0	/* no error */
#define 	ERR_NO_EMPTY_TASK		-1
#define		ERR_EMPTY_TASK_BEYOND	-1
#define		ERR_TASKID_NOT_MATCH	-1
#define		ERR_TASKHANDLE_INVALID	-1
#define		EINVAL					22	/* Invalid argument */
#define		EAGAIN					11	/* Try again */

/*
*********************************************************************************************************
*                                          TASK CONTROL BLOCK
*********************************************************************************************************
*/
struct wsn_task_section {
	int (*entry)(int event);	/*Pointer of section entry function*/
	uint16	advance;
};
	
struct wsn_task_attr {
	uint16	taskid;
	uint8	n_sections;
	uint32	time_to_complete;
	const struct wsn_task_section 	*section_list;
};
	
struct wsn_task {
	uint32		deadline;	/* Timer point the task must be complete*/
	uint32		delta;		/* */
	int8 		taskindex;	/* Index in task attrib table ,start from 0*/
	uint8		state;		/* Task status:complete,ready,block */
	uint8		section;	/**/
	uint16		event;		/**/
};

struct wsn_empty_task {
union {
	struct wsn_empty_task 	*next;
	struct wsn_task 		task;
}u;
};

struct wsn_task_resource{
	uint8 				res_id;
	uint32 				delta;
};

extern void wsn_task_init(void);

extern void wsn_RequestResource(uint16 res_id,int8 taskid);
extern void wsn_ReleaseResource(int8 taskid);


extern uint8 WSN_TaskHandle(uint16 taskid);
extern int16 WSN_TaskID (uint8 taskhandle);
extern int16 WSN_NewTask(uint16 taskid, uint16 event, int16 time);
extern int16 WSN_RestartTask (uint8 taskhandle, uint16 taskid, uint8 section_id, uint16 event);


/*
*********************************************************************************************************
*                                          THREAD CONTROL BLOCK
*********************************************************************************************************
*/
#ifdef _AVR_
	struct context_info{
		uint8		sph_save;
		uint8		spl_save;
	};
#else
	struct context_info{
		uint32		sp;
	};
#endif

#ifdef _Debug_thread_

typedef void (*wsn_thread_entry_t)(void);

struct wsn_thread_attr {
    void (*entry)(void);			/*Pointer of thread entry function*/
    const char 			*name;
    uint8  				priority;
    uint    			stacksize;
    uint 				*p_stack;
};
struct wsn_thread {
    struct wsn_thread 	*next;		/*Pointer to next thread*/
    uint8   			state;		/**/
    uint8   			priority;	/**/
    int8    			error;		/**/
    struct context_info context;	/**/
    unsigned char 		stack[4];	/**/
};
extern void wsn_thread_init(void);

extern void WSN_Sleep(int timeout);
extern void WSN_SetPriority(uint8 priority);

extern void wsn_context_init(struct context_info *context, 
							 	   void *stack,
							 	   void (*entry)(void *),
							 	   void *param );
extern void wsn_context_switch(struct context_info *old_context, 
							   		   struct context_info *new_context );
#endif


/*
*********************************************************************************************************
*                                          BACKGROUND TASKS  CONTROL BLOCK
*********************************************************************************************************
*/

extern void wsn_backtask_init(void);
extern bool wsn_backtask_post(void (*tp) ());
extern bool wsn_run_next_backtask (void);


/*
*********************************************************************************************************
*                                          EVENT CONTROL BLOCK
*********************************************************************************************************
*/
#ifdef _Debug_thread_

struct wsn_event {
	struct wsn_thread 	*wait;		/* wait queue of this event */
	uint8				auto_reset;	/* nonzero value mean auto reset */
	uint8				state;		/* state of event, nonzero means event is set*/
};

extern void WSN_InitEvent(struct wsn_event * p_event, uint8 auto_reset, uint8 state);
extern int  WSN_WaitEvent(struct wsn_event * p_event, int timeout);
extern void WSN_SetEvent(struct wsn_event * p_event);
extern void WSN_ClearEvent(struct wsn_event * p_event);
#endif
/*
*********************************************************************************************************
*                                          SEMAPHORE CONTROL BLOCK
*********************************************************************************************************
*/
#ifdef _Debug_thread_

struct wsn_semaphore {
	struct wsn_thread 	*wait;
	uint8				value;
};

extern void WSN_InitSem(struct wsn_semaphore * p_sem, uint8 value);
extern int  WSN_WaitSem(struct wsn_semaphore * p_sem, int timeout);
extern void WSN_SignalSem(struct wsn_semaphore * p_sem);
#endif
/*
*********************************************************************************************************
*                                          TIMER CONTROL BLOCK
*********************************************************************************************************
*/
struct wsn_timer;
typedef void (*timer_func)(struct wsn_timer * timer);

struct wsn_timer {
    timer_func	func;
    uint16		expire;
    uint8		index;
};

#define WSN_IsTimerOn(timer)	timer->index

extern void wsn_timer_init(void);
extern void wsn_timer_tick (void);
extern int Wsn_TimerTask(int);

extern void  WSN_InitTimer(struct wsn_timer * timer, timer_func func);
extern int8  WSN_StartTimer(struct wsn_timer * timer, uint16 timeout);
extern void  WSN_StopTimer(struct wsn_timer * timer);

extern uint32 WSN_GetSystemTime(void);
extern uint16 WSN_GetSystemTime_16(void);
extern uint32 Wsn_TaskSchedTime(void);

/*
*********************************************************************************************************
*                                          DAYTIME DATA TYPES
*********************************************************************************************************
*/

struct wsn_daytime {
    uint8 second;
    uint8 minute;
    uint8 hour;
    uint8 date;
    uint8 month;
    uint8 year;
};

extern void   WSN_GetDayTime(struct wsn_daytime * p_daytime);
extern void   WSN_SetDayTime(struct wsn_daytime * p_daytime);
extern void   WSN_AdjustDay(uint16 seconds);

/*
*********************************************************************************************************
*                                            GLOBAL VARIABLES
*********************************************************************************************************
*/

#ifdef   WSN_GLOBALS
#define  WSN_EXTERN
#else
#define  WSN_EXTERN  extern
#endif


WSN_EXTERN struct wsn_task 			wsn_task_list[WSN_MAX_ACTIVE_TASKS];	/*Table of all task control blocks*/
WSN_EXTERN struct wsn_task 			*wsn_task_queue[WSN_MAX_ACTIVE_TASKS];	/*Table of all released task pointer*/
WSN_EXTERN struct wsn_empty_task 	*wsn_empty_task_list;	/*Pointer to list of free task TCBs*/

#ifdef _Debug_thread_
WSN_EXTERN struct wsn_thread 		*wsn_thread_queue;		/*Linked list of ready status thread*/
WSN_EXTERN struct wsn_thread 		*wsn_current_thread;	/*Pointer to current running thread*/
#endif

WSN_EXTERN struct context_info		wsn_thread0_context;	/*Context of Task*/

WSN_EXTERN uint8 					wsn_task_nopreempt;		/*Task Preempt control*/

WSN_EXTERN volatile uint8 			wsn_disable_sched;		/*Schedule Lock control, 0-enable sched;1-disable sched*/

WSN_EXTERN uint8 					wsn_int_nesting; 		/*Interrupt nesting level*/

WSN_EXTERN volatile uint8 			wsn_sched_mode;			/*Sched mode: task, thread, none */








/*
*********************************************************************************************************
*                              RTOS STATUS 
*********************************************************************************************************
*/

/*wsn_sched_mode*/
#define	NONE_SCHED			0u
#define TASK_SCHED	    	1u
#define THREAD_SCHED	    2u
#define BACKGROUND_SCHED	3u

/*task status*/
#define TASK_COMPLETE	    0u
#define TASK_BLOCKED	    1u
#define TASK_READY	    	2u
	
/*thread status*/
#define	THREAD_READY	    1u
#define	THREAD_BLOCKED	    2u

/*sched lock*/
#define	SCHED_UNLOCK		0u
#define SCHED_LOCK			1u

/*want sched flag*/
#define	WANTSCHED_RESET	0u
#define	WANTSCHED_SET	1u

/*event state*/
#define MANUAL_RESET		0u
#define AUTO_RESET			1u
#define EVENT_RESET			0u
#define EVENT_SET			1u

/*
*********************************************************************************************************
*                              FUNCTIONS 
*********************************************************************************************************
*/

#define WSN_DisablePreempt()	wsn_task_nopreempt = 1
#define WSN_SchedOff()			wsn_disable_sched = SCHED_LOCK
#define	CONSTAINT_MINI_TO_TICKS(x)  (((uint32)(x)*TICKS_PER_SECOND)/1000)//x means ms add by han
#define MINI_TO_TICKS(x)    		(((uint32)(x)*TICKS_PER_SECOND)/1000)

typedef int (*fn_int_ptr)(int);

extern void wsn_sched(void);
extern void  WSN_SchedOn(void);
extern void wsn_EnterCritical(void);
extern void wsn_LeaveCritical(void);
extern void wsn_system_sleep(void);

/*
*********************************************************************************************************
*                              UART DEBUG OUT 
*********************************************************************************************************
*/
#ifdef UNUSED_CODE
	extern void k_printf_P(const char * fmt,...);
#define WSN_DebugOut  k_printf
#define WSN_DebugOut_P  k_printf_P
#endif
	extern void k_printf( const char *fmt, ... );
#define WSN_Assert   k_printf
	
	
#ifdef WSN_LOG
	/* used to output the formal log info */
#define WSN_print(key, n_p, ...) WSN_printf(key, n_p, ##__VA_ARGS__)
#else
#define WSN_print(key, n_p, ...) 
#endif
	
	
#ifdef WSN_LOG_MORE
	/* used to output the help log info, more details */
#define WSN_debug(key, n_p, ...) WSN_printf(key, n_p, ##__VA_ARGS__)
#else
#define WSN_debug(key, n_p, ...)
#endif
	
#define ASSERT(cond) if (!(cond)) WSN_debug(0x0000, 0)

extern void WSN_printf(uint16 msg_id, uint8 n_params, ...);
extern bool SerialBufferHaveData(void);

/*
*********************************************************************************************************
*                              READ DATA FROM FLASH 
*********************************************************************************************************
*/
#ifdef _AVR_
#include	<avr/pgmspace.h>
#define FLASH PROGMEM
#define flash_read_word(x) pgm_read_word(&x)
#define flash_read_dword(x) pgm_read_dword(&x)
#define flash_read_byte(x) pgm_read_byte(&x)
#else 
#define FLASH 
#define flash_read_word(x) (x)
#define flash_read_dword(x) (x)
#define flash_read_byte(x) (x)
#endif


#endif //__WSN_RTOS_H__


